<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>12、Proxy——this问题</title>
	</head>
	<body>
		<script type="text/javascript">
			//四、this问题
			//虽然 Proxy 可以代理针对目标对象的访问，但它不是目标对象的透明代理，即不做任何拦截的情况下，也无法保证与目标对象的行为一致。主要原因就是在 Proxy 代理的情况下，目标对象内部的this关键字会指向 Proxy 代理。
			const target = {
				m:function(){
					console.log(this === proxy);
				}
			};
			const handler = {};
			const proxy = new Proxy(target,handler);
			target.m();  //false
			proxy.m();   //true
			//上面代码中，一旦proxy代理target.m，后者内部的this就是指向proxy，而不是target。
			//下面是一个例子，由于this指向的变化，导致 Proxy 无法代理目标对象。
			const _name = new WeakMap();
			class Person {
				constructor(name){
					_name.set(this,name);
				}
				get name(){
					return _name.get(this);
				}
			}
			const jane = new Person('Jane');
			console.log(jane.name)   //Jane
			
			const proxy_1 = new Proxy(jane,{});
			console.log(proxy_1.name)  //undefined
			//上面代码中，目标对象jane的name属性，实际保存在外部WeakMap对象_name上面，通过this键区分。由于通过proxy.name访问时，this指向proxy，导致无法取到值，所以返回undefined。
			//此外，有些原生对象的内部属性，只有通过正确的this才能拿到，所以 Proxy 也无法代理这些原生对象的属性。
			const target_1 = new Date();
			const handler_1 = {};
			const proxy_2 = new Proxy(target_1,handler_1);
//			console.log(proxy_2.getDate())  //Uncaught TypeError: this is not a Date object.
			//上面代码中，getDate方法只能在Date对象实例上面拿到，如果this不是Date对象实例就会报错。这时，this绑定原始对象，就可以解决这个问题。
			const target_2 = new Date('2015-01-01');
			const handler_2 = {
				get(target_2,prop){
					if(prop === 'getDate'){
						return target_2.getDate.bind(target_2)
					}
					return Reflect.get(target_2,prop);
				}
			};
			const proxy_3 = new Proxy(target_2,handler_2);
			console.log(proxy_3.getDate())  //1
		</script>
	</body>
</html>
